home *** CD-ROM | disk | FTP | other *** search
- name whereis
- title 'WHEREIS -- find file'
- page 55,132
- ;
- ; WHEREIS -- find file in directory structure
- ; by John Scotia, first published in Softalk/IBM
- ; modified by Ray Duncan
- ;
- lf equ 0ah ;ASCII line feed
- cr equ 0dh ;ASCII carriage return
- ff equ 0ch ;ASCII form feed
- tab equ 09h
- eom equ '$' ;end of message flag
- ;
- ;Program Segment Prefix
- default_fcb equ 05ch
- command equ 80h
- default_dta equ 080h
- ;
- ;
-
- ; This is the format for the DOS Data Transfer Area used when DOS 2.0
- ; searches for a file match in directories.
-
- DTA STRUC
- RESERVED DB 21 DUP (?)
- ATTRIBUTE DB 0
- TIME DW 0
- DATE DW 0
- SIZE DD 0
- NAME_FOUND DB 13 DUP (?)
- DTA ENDS
-
- cseg segment para public 'CODE'
-
- assume cs:cseg,ds:data,es:data,ss:stack
-
- page
-
- ; This is the main program that sets up the initial conditions for
- ; SDIR which, in turn, does a recursive search.
- ;
- ; Reads: PATH_NAME
- ; Writes: FILE_NAME
- ; Calls: SDIR
-
- whereis proc far
-
- push ds ;save final return
- xor ax,ax
- push ax
- mov bp,sp ;save pointer to final return
- ; in case we want to exit
- ; inside recursive routine
-
- mov ax,data ;make data segment addressable
- mov es,ax ;via ES
-
- call infile ;get name of search target
-
- mov ax,data ;make data segment addressable
- mov ds,ax ;via DS
- jnc whereis1 ;jump if filename was ok
- ;filename was missing,
- mov dx,offset msg1 ;print error message and exit
- mov ah,9
- int 21h
- ret
- whereis1:
- mov ah,30h ;check DOS version
- int 21h
- cmp al,2
- jae whereis2 ;proceed, DOS 2.0 or greater
- mov dx,offset msg3 ;DOS 1.1 --- print message
- mov ah,9 ;and exit
- int 21h
- ret
- whereis2:
- MOV DI,OFFSET PATH_NAME
- XOR AL,AL ;Search for the zero at the end
- CLD ; of PATH_NAME
- MOV CX,64 ;Max. length of scan for 0
- REPNZ SCASB
- MOV BX,DI
- DEC BX ;DS:BX points to end of PATH_NAME
- MOV DX,0 ;Tell SDIR this is first
- CALL SDIR ;Now do the recursive search
- mov ax,match_count ;were any matches found?
- or ax,ax
- jz whereis8 ;no,jump
- ret ;yes,just exit
- whereis8:
- mov dx,offset msg2 ;no,print "no match"
- mov ah,9
- int 21h
- ret
- ;this is a special crash
- ;exit, which may be taken
- ;from inside recursed proc.
- whereis9:
- mov sp,bp
- ret
-
- whereis endp
-
- page
-
- ; This procedure searches all the files in the current directory
- ; looking for a match. It also prints the full name for each match.
- ;
- ; DS:BX Pointer to end of current path name
- ; DS:DX Old disk transfer area (DTA)
- ;
- ; Reads: Disk Transfer Area (DTA)
- ; Writes: Disk Transfer Area (DTA)
- ; Calls: BUILD_NAME, FMATCH, PNAME
- ; NMATCH, BUILD_STAR_NAME, SSUB
-
- SDIR PROC NEAR
- PUSH SI ;Need to restore on exit
- PUSH DX
- CALL BUILD_NAME ;Build the absolute search name
- CALL FMATCH ;See if there is a match here
- JC sdir2 ;No match, check subdirectories
- CALL PNAME ;Write name of match.
- sdir1:
- CALL NMATCH ;Find the next match
- JC sdir2 ;No match, search sub-directories
- CALL PNAME ;Match, write absolute name
- JMP sdir1 ;Look for the next matching name
- sdir2: ;No match, so try sub-directories.
- POP DX ;Restore DTA
- PUSH DX
- CALL BUILD_STAR_NAME ;Search for all directories
- CALL FMATCH ;Get first entry
- JC SDIR5 ;There are no entries
- MOV SI,DX ;Put address of DTA into SI
- TEST [SI].ATTRIBUTE,10H ;Is it a directory entry?
- JNZ SDIR4 ;Yes, then search sub-directory
- SDIR3:
- CALL NMATCH ;No, then find the next match
- JC SDIR5 ;There are no more entries
- TEST [SI].ATTRIBUTE,10H ;Is this a directory?
- JZ SDIR3 ;No, then try again
- SDIR4:
- CMP [SI].NAME_FOUND,'.' ;Is this a . or .. directory?
- JE SDIR3 ;Yes, skip to next directory
- CALL SSUB ;Search the sub-directory
- PUSH AX ;Now reset the DTA
- MOV AH,1AH
- INT 21H
- POP AX
- JMP SDIR3
-
- SDIR5:
- POP DX
- POP SI
- RET
- SDIR ENDP
-
- page
-
- ; This procedure searches the subdirectory whos name is in the DTA
- ;
- ; DS:BX End of the current path name
- ; DS:[DX].NAME_FOUND Name of subdirectory for search
- ; Reads: PATH_NAME
- ; Writes: PATH_NAME
- ; Calls: SDIR
-
- SSUB PROC NEAR
- PUSH DI
- PUSH SI
- PUSH AX
- PUSH BX
- CLD ;Set for increment
- MOV SI,DX ;Put address of DTA into SI
- ADD SI,OFFSET NAME_FOUND ;Set to start of sub-directory name
- MOV DI,BX ;DS:DI -- 0 at end of path name
- ssub1: ;Copy sub-directory to path name
- LODSB ;Copy one character
- STOSB
- OR AL,AL ;Was it a 0?
- JNZ ssub1 ;No, keep copying
- MOV BX,DI ;Set BX to end of new path name
- STD ;Set flag for decrement
- STOSB ;Store a 0 at end of string
- MOV AL,'\'
- STOSB ;Place '\' at end of path name
- CALL SDIR ;Search this new path
- POP BX ;Restore the old end-of-path
- MOV BYTE PTR [BX],0 ;And store a zero here
- POP AX
- POP SI
- POP DI
- RET
- SSUB ENDP
-
- page
-
- ; This procedure prints the matched name after the path name
- ;
- ; DS:DX Pointer to current disk transfer area
- ;
- ; Reads: PATH_NAME, NAME_FOUND (in DTA)
- ; Calls: pasciiz, CRLF
-
- PNAME PROC NEAR
- PUSH AX
- PUSH DX
- MOV DX,OFFSET PATH_NAME
- MOV AL,[BX] ;Save character at end of path
- MOV BYTE PTR [BX],0 ;Set for end of string
- CALL pasciiz
- MOV [BX],AL ;Restore character
- POP DX ;Recover old pointer
- PUSH DX
- ADD DX,OFFSET NAME_FOUND
- CALL pasciiz
- cmp byte ptr switch,'g' ;global switch set?
- je pname2 ;yes,keep searching
- ;no, check if user wants
- ;to keep looking.
- push dx ;save current DTA
- mov dx,offset msg4 ;print 'More? '
- mov ah,9
- int 21h
- mov ah,7 ;read console without echo
- int 21h
- or al,20h ;fold to lower case
- cmp al,'y' ;must be y, anything else exits
- je pname1
- jmp whereis9 ;take crash exit
- pname1: mov dl,al ;if Y,echo it
- mov ah,2
- int 21h
- pop dx ;restore pointer to DTA
- pname2: CALL CRLF
- inc match_count ;count names displayed
- POP DX
- POP AX
- RET
- PNAME ENDP
-
- page
-
- ; This procedure builds an absolute search name from PATH_NAME
- ; followed by FILE_NAME.
- ;
- ; Reads: FILE_NAME
- ; Calls: BUILD to build the name
-
- BUILD_NAME PROC NEAR
- PUSH SI
- MOV SI,OFFSET FILE_NAME
- CALL BUILD
- POP SI
- RET
- BUILD_NAME ENDP
-
- BUILD_STAR_NAME PROC NEAR
- PUSH SI
- MOV SI,OFFSET STAR_NAME
- CALL BUILD
- POP SI
- RET
- BUILD_STAR_NAME ENDP
-
- ; This procedure appends the string at DS:SI to PATH_NAME in
- ; PATH_NAME. It knows where the path name ends from knowing how
- ; long PATH_NAME is.
- ;
- ; DS:SI Name of file
- ; DS:BX End of PATH_NAME
- ;
- ; Reads: DS:SI
- ; Writes: PATH_NAME
-
- BUILD PROC NEAR
- PUSH AX
- PUSH DI
- MOV DI,BX
- CLD ;Set direction for increment
- build1:
- LODSB ;Copy one character of name
- STOSB
- OR AL,AL ;End of string yet?
- JNZ build1 ;No, keep copying
- POP DI
- POP AX
- RET
- BUILD ENDP
-
- page
-
- ; This procedure finds the first match between the name given by
- ; DS:DX and the directory entries found in the directory PATH_NAME.
- ;
- ; DS:DX Pointer to current disk transfer area
- ; Returns:
- ; CF 0 A match was found
- ; 1 No match found
- ; AX Error code returned:
- ; 2 File not found
- ; 18 No more files
- ; DS:DX Pointer to new disk transfer area
- ;
- ; Reads: PATH_NAME
- ; Writes: dbuff
-
- FMATCH PROC NEAR
- PUSH CX
- CMP DX,0 ;First one?
- JA ALLOCATE ;No, then allocate space
- MOV DX,OFFSET dbuff-TYPE DTA
- allocate:
- add dx,type dta ;no, then allocate room for new DTA
- MOV CX,10H ;Search attribute for files and dirs.
- MOV AH,1AH ;Set disk transfer address
- INT 21H
- PUSH DX ;Need DX for address of search name
- MOV DX,OFFSET PATH_NAME
- MOV AH,4EH ;Call for "find first match"
- INT 21H
- POP DX
- POP CX
- RET ;Return with carry flag info
- FMATCH ENDP
-
-
- page
-
- ; Get next match for filename
- ; (very similar to Get first match routine)
-
- ; Returns:
- ; CF 0 A match was found
- ; 1 No match found
- ; AX Error code returned:
- ; 2 File not found
- ; 18 No more files
- ;
- ; Reads: PATH_NAME
- ; Writes: dbuff
-
- NMATCH PROC NEAR
- PUSH CX
- PUSH DX
- MOV DX,OFFSET PATH_NAME
- MOV CX,10H ;Attribute for files and directories
- MOV AH,4FH ;Call for "Find next match"
- INT 21H
- POP DX
- POP CX
- RET ;Return with carry flag intact
- NMATCH ENDP
-
-
- page
-
- ; Send CRLF sequence to the screen.
-
- CRLF PROC NEAR
- PUSH AX
- PUSH DX
- MOV AH,02
- MOV DL,0AH
- INT 21H
- MOV DL,0DH
- INT 21H
- POP DX
- POP AX
- RET
- CRLF ENDP
-
- page
-
- ; Display ASCIIZ string
- ; Call with DS:DX = string addr
-
- pasciiz PROC NEAR
- PUSH AX
- PUSH DX
- PUSH SI
- CLD ;Set direction for increment
- MOV SI,DX ;Set up pointer to string
- MOV AH,2
- pasciiz1:
- LODSB ;Get character
- or al,al ;if zero,all done
- jz pasciiz2
- MOV DL,AL
- INT 21H ;Write one character
- jmp pasciiz1 ;loop till string exhausted
- pasciiz2:
- POP SI
- POP DX
- POP AX
- RET
- pasciiz ENDP
-
- page
-
-
- infile proc near ;process name of input file
- ;DS:SI <- addr command line
- mov si,offset command
- ;ES:DI <- addr filespec buffer
- mov di,offset file_name
- cld
- lodsb ;any command line present?
- or al,al ;return error status if not.
- jz infile4
- infile1: ;scan over leading blanks
- lodsb ;to file name
- cmp al,cr ;if we hit carriage return
- jz infile4 ;filename is missing.
- cmp al,20h ;is this a blank?
- jz infile1 ;if so keep scanning.
- xor ah,ah ;reset "." found flag
- ;found first char of name
- infile2:
- cmp al,'\' ;if slash,reset "." flag
- jne infile22
- xor ah,ah
- infile22: ;check if extension specified
- cmp al,'.'
- jne infile24
- inc ah
- infile24: ;
- stosb ;move last char. to output
- ;file name buffer.
- lodsb ;check next character, found
- cmp al,cr ;carriage return yet?
- je infile3 ;yes,exit with success code
- cmp al,'/' ;or if we hit a switch delimiter
- jne infile26
- infile25:
- lodsb ;get the switch char and save it
- or al,20h ;force to lower case
- mov byte ptr es:switch,al
- jmp infile3 ;then jump to finish up
- infile26:
- cmp al,20h ;is this a blank?
- jne infile2 ;if not keep moving chars.
- infile27:
- lodsb ;search up to end, in case of switch
- cmp al,'/'
- je infile25 ;found switch,go save it
- cmp al,cr
- jne infile27 ;otherwise, fscan until CR found
- infile3: ;found end of input name
- or ah,ah ;was "." found?
- jnz infile35 ;yes,jump
- mov al,'.' ;no,force ext to wildcard
- stosb
- mov al,'*'
- stosb
- infile35:
- xor al,al ;store trailing null byte
- stosb ;exit with CY=0 as success flag
- clc
- ret
-
- infile4: ;exit with carry =1
- stc ;for error flag
- ret
- infile endp
-
- cseg ends
-
- page
-
- data segment para public 'DATA'
-
- STAR_NAME DB '*.*',0
-
- PATH_NAME DB '\',0
- DB 80 DUP (0) ;Space for 64 character path name
- ; and 13 character file name
-
- FILE_NAME DB 13 DUP (0) ;Save room for full DOS file name
-
- msg1 db cr,lf
- db 'Missing file name.'
- db cr,lf,eom
-
- msg2 db cr,lf
- db 'No match found.'
- db cr,lf,eom
-
- msg3 db cr,lf
- db 'Requires DOS version 2.0 or greater.'
- db cr,lf,eom
-
- msg4 db tab,' More (y/n) ? ',eom
-
- match_count dw 0 ;number of filenames matching
- ;input filespec
-
- switch db 0 ;char following / saved here
-
- dbuff equ $ ;this starts the scratch area
- ;which will be used as search
- ;buffers. It is right under
- ;the stack, which is made very
- ;large to give it room.
-
- data ends
-
-
- stack segment para stack 'STACK'
- db 32768 dup (?)
- stack ends
-
-
- end whereis
-